#!/usr/bin/env python
# encoding: utf-8
"""
google_reader.py

Created by Bertrand Cachet on 2009-06-02.
Copyright (c) 2009 __MyCompanyName__. All rights reserved.
"""

import cookielib
import urllib2
import re

if __name__ == "__main__":
    import sys
    import os
    sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
    
from social_box.service import Service
from feed import GoogleReaderFeed, GoogleReaderObject

class CredentialError(Exception):
    pass

def require_SID(func):
    def wrapper(self, *arg, **kw):
        if self._SID == None:
            self.get_SID()
        return func(self, *arg, **kw)
    return wrapper

def parse_response(func):
    def wrapper(self, *arg, **kw):
        response = func(self, *arg, **kw)
        google_obj = GoogleReaderObject(response)
        return google_obj.parse()
    return wrapper

class GoogleReaderService(Service):
    """Class to connect to reader.google.com service."""
    def __init__(self, username, password):
        super(GoogleReaderService, self).__init__(username, password)
        self._source = 'python-googlereader-contact:pyrfeed-at-gmail/0.1'

        self._google_url = 'http://www.google.com'
        self._reader_url = self._google_url + '/reader'
        self._login_url = 'https://www.google.com/accounts/ClientLogin'
        self._token_url = self._reader_url + '/api/0/token'
        self._subscription_list_url = self._reader_url + '/api/0/subscription/list'
        self._reading_url = self._reader_url + '/atom/user/-/state/com.google/reading-list'
        self._read_items_url = self._reader_url + '/atom/user/-/state/com.google/read'
        self._reading_tag_url = self._reader_url + '/atom/user/-/label/%s'
        self._starred_url = self._reader_url + '/atom/user/-/state/com.google/starred'
        self._subscription_url = self._reader_url + '/api/0/subscription/edit'
        self._get_feed_url = self._reader_url + '/atom/feed/'

        self._SID = None

    def get_SID(self):
        """
        Will log with reader.google service using (username, password)
        credentials.
        The Session ID that will be fetched from reader.google service
        will be later used when sending request to the service.
        """
        
        self._SID = None
        post_args = {   'Email': self._username,
                                    'Passwd': self._password,
                                    'service': 'reader',
                                    'source': self._source,
                                    'continue': self._google_url, }
        try:
            SID_data = self._fetcher.get(self._login_url, post_args)
            if SID_data:
                self._SID =  re.search('SID=(\S*)', SID_data).group(1)
            if self._SID != None:
                cookie = cookielib.Cookie(version=0, name='SID', value= self._SID, expires='1600000000',
                                                                path='/', path_specified=True,
                                                                domain='.google.com', domain_specified=True, domain_initial_dot=True,
                                                                
                                                                port=None, port_specified=False, secure=False, discard=False,
                                                                comment=None,comment_url=None,rest={}
                                                                )
                self._fetcher.add_cookie(cookie)
        except urllib2.HTTPError, e:
            if e.code == 403:
                raise CredentialError('Invalid password or username')
            else:
                raise e

    @require_SID
    def get_results(self, url, post_args=None):
        """
        Every functionalities are associated to an URL.
        This method handles the URL, creating the header, attaching the
        cookie and retrieving the data from google.
        Return data as a raw data string. Will need to parse it later.
        """
        return self._fetcher.get(url, post_args)

    @parse_response
    def get_feed(self, url):
        """
        Get a specific feed.  It works for any feed, subscribed or not
        """
        return self.get_results( self._get_feed_url + url.encode('utf-8'))

    @parse_response
    def get_subscription_list(self):
        """
        Get a list of the users subscribed feeds
        """
        return self.get_results( self._subscription_list_url)

    
    def get_all(self, tag=None):
        """
        Get a feed of the users unread items
        """
        if tag != None:
            resp = self.get_results( self._reading_tag_url % tag)
        else:
            resp = self.get_results( self._reading_url)
        return [entry for entry in GoogleReaderFeed(resp).get_entries()]

    def get_unread(self):
        """
        Get a feed of the users read items
        """
        return [entry for entry in GoogleReaderFeed(self.get_results( self._read_items_url)).get_entries()]

    def get_starred(self):
        """
        Get a feed of a users starred items/feeds
        """
        return [entry for entry in GoogleReaderFeed(self.get_results(self._starred_url)).get_entries()]

    def get_token(self):
        """
        Get a token, this is needed for modifying to reader
        """
        return self.get_results( self._token_url)

    def modify_subscription(self, what, do):
        """
        Subscribe/Unsubscribe to a feed
        """
        url = self._subscription_url + '?client=%s' % self._source
        post_args = {'ac': do, 's': "feed/" + what, 'T': self.get_token()}
        return self.get_results(url, post_args)

    def add_subscription(self, url):
        """
        Subscribe to a feed
        """
        return self.modify_subscription(url, 'subscribe')

    def remove_subscription(self, url):
        """
        Unsubscribe to a feed
        """
        return self.modify_subscription(url, 'unsubscribe')

def main():
    s = GoogleReaderService('test.socialbox', 'S0ci@lB0x')
    print s.get_subscription_list()
    s.add_subscription('http://www.framasoft.net/spip.php?page=backend&id_rubrique=338')
    print s.get_subscription_list()
    #print s.get_read_items()
    items = s.get_all()
    for entry in items:
        print '#'*20
        print 'Entry', entry

    s.remove_subscription('http://www.framasoft.net/spip.php?page=backend&id_rubrique=338')
    print s.get_subscription_list()



if __name__ == "__main__":
    main()
